package cn.com.nes.site.modules.opportuntiy;

import cn.com.nes.common.util.CopyUtils;
import cn.com.nes.mybatis.agent.crm.entity.Opportunity;
import cn.com.nes.mybatis.agent.crm.entity.OpportunityDeviceModel;
import cn.com.nes.mybatis.agent.crm.entity.OpportunityEnergyType;
import cn.com.nes.mybatis.agent.ope.entity.SaleOrderInfo;
import cn.com.nes.mybatis.agent.project.entity.ProjectCustomerRelationship;
import cn.com.nes.site.entity.em.crm.customer.EnergyTypeEnum;
import cn.com.nes.site.entity.em.crm.opportunity.AllowanceTarget;
import cn.com.nes.site.entity.em.crm.opportunity.AllowanceTypeEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityClassificationEnum;
import cn.com.nes.site.entity.em.crm.opportunity.RenovationType;
import cn.com.nes.site.service.crm.opportunity.bo.OpportunityBO;
import cn.com.nes.site.service.crm.opportunity.bo.QueryOpportunityPageBO;
import cn.com.nes.site.service.crm.opportunity.dto.OpportunityAreaCodeDTO;
import cn.com.nes.site.service.crm.opportunity.dto.OpportunityDeviceModelDTO;
import cn.com.nes.site.service.crm.opportunity.dto.OpportunityInfoDto;
import cn.com.nes.site.service.crm.order.SaleOrderInfoService;
import cn.com.nes.site.service.crm.order.bo.QueryHaveWorkOrderBO;
import cn.com.nes.site.service.project.ProjectCustomerRelationshipService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 政府公共项目业务处理
 */
@Slf4j
@Service
public class GovernmentPublicOpportunityHandle extends CommonOpportunityHandle {

    @Resource
    private ProjectCustomerRelationshipService projectCustomerRelationshipService;

    @Resource
    private SaleOrderInfoService saleOrderInfoService;

    public GovernmentPublicOpportunityHandle() {
        log.debug("GovernmentPublicOpportunityHandle instance ....");
    }

    /**
     * 商务项目类型
     * @return
     */
    @Override
    public OpportunityClassificationEnum opportunityClassification() {
        return OpportunityClassificationEnum.GOVERNMENT_PUBLIC;
    }

    @Override
    protected void settingDefaultFields(OpportunityBO opportunityBO, Opportunity opportunity) {
        super.settingDefaultFields(opportunityBO, opportunity);

        log.debug("GovernmentPublicOpportunityHandle setting default fields ....");
        opportunity.setPlanYear(opportunityBO.getPlanYear());
        opportunity.setAllowanceType(opportunityBO.getAllowanceType());
        opportunity.setAllowanceTarget(ObjectUtil.isNull(opportunityBO.getAllowanceTarget()) ? null :opportunityBO.getAllowanceTarget().getKey());
        opportunity.setAllowanceDown(opportunityBO.getAllowanceDown());
        opportunity.setAllowanceUp(opportunityBO.getAllowanceUp());
        opportunity.setAllowanceAmountOfMoney(opportunityBO.getAllowanceAmountOfMoney());

        opportunity.setPlanInstallPeoples(opportunityBO.getPlanInstallPeoples());
        opportunity.setRenovationType(ObjectUtil.isNull(opportunityBO.getRenovationType()) ? null : opportunityBO.getRenovationType().getKey());

        opportunity.setAllowDeviceBrandType(CollUtil.join(opportunityBO.getAllowDeviceBrandTypes(), ";"));
        opportunity.setAllowDeviceEnergyType(CollUtil.join(opportunityBO.getAllowDeviceEnergyTypes(), ";"));
    }

    @Override
    protected void handleDefaultFieldsForOpportunityBaseInfo(OpportunityInfoDto opportunityInfoDto) throws Exception {
        super.handleDefaultFieldsForOpportunityBaseInfo(opportunityInfoDto);
        log.debug("GovernmentPublicOpportunityHandle handle default fields for opportunity base info ....");
        // 允许的行政区划范围处理
        List<OpportunityAreaCodeDTO> areaCodeDTOS = opportunityAreaCodeService.getAreaCodesByOpportunityUuid(opportunityInfoDto.getUuid());
        opportunityInfoDto.setAllowAreaCodes(areaCodeDTOS);
        // 能源类型处理
        List<OpportunityEnergyType> energyTypes = opportunityEnergyTypeService.getEnergyTypes(opportunityInfoDto.getUuid());
        opportunityInfoDto.setAllowEnergyTypes(CollUtil.isEmpty(energyTypes) ? Collections.emptyList() : energyTypes.stream()
                .map(OpportunityEnergyType::getEnergyType)
                .collect(Collectors.toList()));
        // 能源类型名称处理
        opportunityInfoDto.setAllowEnergyTypeNames(CollUtil.isEmpty(energyTypes) ? Collections.emptyList() : energyTypes.stream()
                .map(energyType -> EnergyTypeEnum.getEnum(energyType.getEnergyType()).getValue())
                .collect(Collectors.toList()));
        // 允许的设备型号处理
        List<OpportunityDeviceModel> deviceModels = opportunityDeviceModelService.getDeviceModels(opportunityInfoDto.getUuid());
        opportunityInfoDto.setAllowDeviceModels(CollUtil.isNotEmpty(deviceModels) ? CopyUtils.copyList(deviceModels, OpportunityDeviceModelDTO.class) : Collections.emptyList());

        // 允许的设备品牌处理
        opportunityInfoDto.setAllowDeviceBrandTypes(StrUtil.isNotEmpty(opportunityInfoDto.getAllowDeviceBrandType()) ? Arrays.asList(opportunityInfoDto.getAllowDeviceBrandType()
                .split(";")) : Collections.emptyList());
        // 允许的设备能源分类处理
        opportunityInfoDto.setAllowDeviceEnergyTypes(StrUtil.isNotEmpty(opportunityInfoDto.getAllowDeviceEnergyType()) ? Arrays.asList(opportunityInfoDto.getAllowDeviceEnergyType()
                .split(";")) : Collections.emptyList());
        // 允许的补贴方式处理
        opportunityInfoDto.setAllowanceTypeName(AllowanceTypeEnum.enumConvertKeyToValue(opportunityInfoDto.getAllowanceType()));
        // 补贴对象名称处理
        opportunityInfoDto.setAllowanceTargetName(AllowanceTarget.enumConvertKeyToValue(opportunityInfoDto.getAllowanceTarget()));
        // 改造类型名称处理
        opportunityInfoDto.setRenovationTypeName(RenovationType.enumConvertKeyToValue(opportunityInfoDto.getRenovationType()));
    }

    @Override
    protected void handleDefaultConditionForPage(QueryOpportunityPageBO bo) {
        if (StrUtil.isEmpty(bo.getMainOpportunityUuid())) {
            super.handleDefaultConditionForPage(bo);
            log.debug("GovernmentPublicOpportunityHandle handleOpportunityClassification ....");
        } else {
            log.debug("GovernmentPublicOpportunityHandle handle add [RETAIL、END_USRE]....");
            bo.setOpportunityClassifications(Arrays.asList(OpportunityClassificationEnum.RETAIL.getKey(), OpportunityClassificationEnum.END_USRE.getKey()));
            // 是否查询关联数据，true-查询已关联数据，false-查询未关联数据，排除掉已关联的
            if(ObjectUtil.isNotNull(bo.getRelatedQuery()) && bo.getRelatedQuery()) {
                handleRelatedOpportunitys(bo);
            } else {
                handleExcludeRelatedOpportunitys(bo);
            }
        }
    }

    private void handleExcludeRelatedOpportunitys(QueryOpportunityPageBO bo) {
        try {
            List<ProjectCustomerRelationship> beRelatedOfRelationships = projectCustomerRelationshipService.getBeRelatedOfRelationships(bo.getMainOpportunityUuid());
            if (CollUtil.isNotEmpty(beRelatedOfRelationships)) {
                List<String> relatedOpportunityUuids = beRelatedOfRelationships.stream()
                        .map(ProjectCustomerRelationship::getBusinessId)
                        .collect(Collectors.toList());
                bo.setExcludeRelatedOpportunityUuids(relatedOpportunityUuids);
            }
        } catch (Exception e) {
            log.error("GovernmentPublicOpportunityHandle handleRelatedOpportunitys error", e);
        }
    }

    /**
     * Handles the retrieval and setting of related opportunity UUIDs for a given main opportunity.
     * This method fetches all project customer relationships where the provided main opportunity is a related entity,
     * then extracts the business IDs (assumed to be opportunity UUIDs) from these relationships, and finally sets them
     * in the provided QueryOpportunityPageBO object. If an error occurs during this process, it logs the exception.
     *
     * @param bo The QueryOpportunityPageBO instance containing the main opportunity UUID and to which the related opportunity UUIDs will be added.
     */
    private void handleRelatedOpportunitys(QueryOpportunityPageBO bo) {
        try {
            List<ProjectCustomerRelationship> beRelatedOfRelationships = projectCustomerRelationshipService.getBeRelatedOfRelationships(bo.getMainOpportunityUuid());
            if (CollUtil.isNotEmpty(beRelatedOfRelationships)) {
                List<String> relatedOpportunityUuids = beRelatedOfRelationships.stream()
                        .map(ProjectCustomerRelationship::getBusinessId)
                        .collect(Collectors.toList());
                bo.setBeRelatedOpportunityUuids(relatedOpportunityUuids);
            } else {
                bo.setBeRelatedOpportunityUuids(Collections.singletonList("-1"));
            }
        } catch (Exception e) {
            log.error("GovernmentPublicOpportunityHandle handleRelatedOpportunitys error", e);
        }
    }

    @Override
    protected void defaultPostHandlePageData(List<OpportunityInfoDto> records, QueryOpportunityPageBO bo) throws Exception {
        log.debug("GovernmentPublicOpportunityHandle default post handle page data ....");
        // 政府终端客户查询销售单信息
        if(StrUtil.isNotEmpty(bo.getMainOpportunityUuid()) && ObjectUtil.isNotNull(bo.getRelatedQuery()) && bo.getRelatedQuery()) {
            List<String> opportunityUuids = records.stream()
                    .map(OpportunityInfoDto::getUuid)
                    .collect(Collectors.toList());

            List<SaleOrderInfo> saleOrders = saleOrderInfoService.getSaleOrders(opportunityUuids);
            Map<String, SaleOrderInfo> opportunityOrderMap = saleOrders.stream()
                    .sorted(Comparator.comparing(SaleOrderInfo::getGmtCreate))
                    .collect(Collectors.toMap(SaleOrderInfo::getBusinessId, // 使用 businessId 作为键
                            order -> order,               // 直接将 order 作为值
                            (existingOrder, newOrder) ->  // 当有重复键时进行合并
                                    existingOrder.getGmtCreate().after(newOrder.getGmtCreate())
                                            ? existingOrder
                                            : newOrder
                    ));
            for (OpportunityInfoDto record : records) {
                SaleOrderInfo saleOrderInfo = opportunityOrderMap.get(record.getUuid());
                record.setSaleOrderId(ObjectUtil.isNotNull(saleOrderInfo) ? saleOrderInfo.getId() : null);
                record.setSaleOrderCommit(ObjectUtil.isNotNull(saleOrderInfo) ? saleOrderInfo.getCommit() : null);
                record.setSaleOrderStatus(ObjectUtil.isNotNull(saleOrderInfo) ? saleOrderInfo.getStatus() : null);

                // 是否已派单
                QueryHaveWorkOrderBO queryBO = new QueryHaveWorkOrderBO(record.getCustomerId(), record.getUuid(), bo.getOperateUserCompanyId());
                record.setHaveWorkOrder(saleOrderInfoService.queryHaveWorkOrder(queryBO));
            }
        }
    }

}
